import {
    FC, ReactNode, useCallback, useEffect, useRef
} from 'react';
import styles from './demo1.module.less';

export interface Demo1Props {
    children?: ReactNode;
}
/**
 * 顶点着色器：用来描述顶点特性
 * 片元着色器：进行逐片元处理程序  计算获取颜色信息，片元可以理解为一个个像素
 */
const Demo1: FC<Demo1Props> = () => {
    const canvasRef = useRef(null);

    const main = useCallback(async (canvas: HTMLCanvasElement) => {
        const gl = canvas.getContext('webgl');
        // 创建着色器资源
        // gl_position vec4(1.0, 0.0, 0.0, 1.0)   x, y, z, w齐次坐标 (w/x, y/w, z/w)
        const VERTEX_SHADER_SOURCE = `
            // 给顶点着色器设置变量
            attribute vec4 aPosition;
            void main() {    
                gl_Position = aPosition; // vec4(0.0, 0.0, 0.0, 1.0);
                gl_PointSize = 10.0;
            }
        `;
        //  gl_fragColor vec4(1.0, 0.0, 0.0, 1.0)  r,g,b,a
        const FRAGMENT_SHADER_SOURCE = `
            // 指定精度 highp   lowp
            precision mediump float;
            // uniform变量也可以用在顶点着色器，但是不能给顶点变量，因为uniform变量不会变化
            uniform vec4 uColor;
            void main() {
                gl_FragColor = uColor;
            }
        `;
        // 创建着色器
        const verShader = gl.createShader(gl.VERTEX_SHADER);
        const fragShader = gl.createShader(gl.FRAGMENT_SHADER);
        // 指定着色器源码
        gl.shaderSource(verShader, VERTEX_SHADER_SOURCE);
        gl.shaderSource(fragShader, FRAGMENT_SHADER_SOURCE);
        // 编译着色器
        gl.compileShader(verShader);
        gl.compileShader(fragShader);

        // 创建一个程序对象
        const program = gl.createProgram();
        // 给程序对象指定使用的着色器
        gl.attachShader(program, verShader);
        gl.attachShader(program, fragShader);
        // 关联gl和程序对象
        gl.linkProgram(program);
        gl.useProgram(program);

        const halfWidth = canvas.offsetWidth / 2;
        const halfHeight = canvas.offsetHeight / 2;
        // 获取attribute变量
        const aPosition = gl.getAttribLocation(program, 'aPosition');
        const uColor = gl.getUniformLocation(program, 'uColor');
        gl.uniform4f(uColor, 1.0, 0.0, 1.0, 1.0); // 这里使用uniform2f的话上面声明得用vec2，赋值的时候 gl_FragColor = ve4(uColor.r, uColor.g, 1.0, 1.0);
        const points = [];

        const handleEvent = (e: MouseEvent) => {
            const clientX = e.clientX;
            const clientY = e.clientY;
            const offsetX = e.offsetX;
            const offsetY = e.offsetY;
            // client:相对屏幕右上角？父级
            // offset:相对元素右上角
            console.log(clientX, clientY, offsetX, offsetY);
            // webgl的uv坐标系和常用的前端坐标系不同，
            // x轴从左到右：-1 0 1
            // y轴从上到下：1 0 -1
            // 坐标轴转换
            const x = (offsetX - halfWidth) / halfWidth;
            const y = (halfHeight - offsetY) / halfHeight;
            // 得到uv坐标系的x和y
            points.push([x, y]);

            for (let i = 0; i < points.length; i++) {
                const p = points[i];
                gl.vertexAttrib2f(aPosition, p[0], p[1]);
                // 绘制点， 从哪个开始  使用几个顶点
                gl.drawArrays(gl.POINTS, 0, 1);
                // gl.drawArrays(gl.LINES, 0, 1);
            }
        };

        canvas.addEventListener('click', handleEvent, false);

        return () => {
            canvas.removeEventListener('click', handleEvent, false);
        };
    }, []);

    useEffect(() => {
        let removeEvent = null;
        if (canvasRef.current) {
            removeEvent = main(canvasRef.current);
        }

        return () => {
            if (typeof removeEvent === 'function') {
                removeEvent?.();
            }
        };
    }, [main]);

    return (
        <div className={styles.demo1}>
            <canvas ref={canvasRef} width="600" height="400" />
        </div>
    );
};

export default Demo1;
